import { AxiosRequestConfig } from "axios"

import { DOMParser } from "xmldom"
import type { Type, CollecterParams } from "../types"
import { isJSON } from "../utils"
const xpath = require("xpath")
const https = require("https")
const axios = require("axios")

const dom = DOMParser

export default async function request(url: string, config: AxiosRequestConfig): Promise<any> {
  try {
    const { data } = await axios.get(url, {
      responseType: "text",
      ...config,
      httpsAgent: new https.Agent({
        rejectUnauthorized: false,
      }),
    })
    return data
  } catch (error) {
    return await request(url, config)
  }
}

export async function requestTypes(url: string): Promise<Type[]> {
  const data = await request(url, { params: { ac: "list" } })

  if (isJSON(data)) {
    return data.class
  }

  const doc = new dom().parseFromString(data)
  const nodes = xpath.select("//class/ty", doc)

  return Array.from(nodes).map((item: any) => {
    const id = xpath.select1("@id", item).value
    const name = item?.firstChild?.data
    return {
      id: Number(id),
      name,
    }
  })
}

export async function requestCount(url: string, params: CollecterParams): Promise<any> {
  const data = await request(url, { params: { ac: "list", ...params } })
  if (isJSON(data)) {
    return {
      pageCount: data.pagecount,
      recordCount: data.total,
    }
  }
  const doc = new dom().parseFromString(data)
  const pageCount = xpath.select1("//list/@pagecount", doc).value
  const recordCount = xpath.select1("//list/@recordcount", doc).value
  return {
    pageCount: Number(pageCount),
    recordCount: Number(recordCount),
  }
}

export async function requestPage(url: string, pg: number, params: CollecterParams): Promise<any> {
  const data = await request(url, {
    params: { ac: "videolist", pg, ...params },
  })

  if (isJSON(data)) {
    return data.list
  }

  const doc = new dom().parseFromString(data)
  const nodes = xpath.select("//list/video", doc)
  if (!nodes || nodes?.length === 0) {
    return null
  }
  return Array.from(nodes).map((item: any) => {
    const last = selectParam(xpath, item, "//last")
    const id = selectParam(xpath, item, "//id")
    const urls = Array.from(xpath.select("//dl/dd", item)).map((node: any) => {
      return {
        flag: xpath.select1("@flag", node).value,
        text: node?.firstChild?.data,
      }
    })

    return {
      last,
      id: Number(id),
      tid: Number(selectParam(xpath, item, "//tid")),
      name: selectParam(xpath, item, "//name"),
      type: selectParam(xpath, item, "//type"),
      pic: selectParam(xpath, item, "//pic"),
      lang: selectParam(xpath, item, "//lang"),
      area: selectParam(xpath, item, "//area"),
      year: Number(selectParam(xpath, item, "//year")),
      state: selectParam(xpath, item, "//state"),
      note: selectParam(xpath, item, "//note"),
      actor: selectParam(xpath, item, "//actor"),
      director: selectParam(xpath, item, "//director"),
      des: selectParam(xpath, item, "//des"),
      urls: JSON.stringify(urls),
    }
  })
}

function selectParam(xpath: any, item: any, selector: any) {
  return xpath.select1(selector, item)?.firstChild?.data || ""
}
